package com.block.source.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.enums.InfoTypeEnum;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.model.dto.SourceCountDTO;
import com.block.common.model.vo.ResultInfoVO;
import com.block.common.service.IApplicationInfoService;
import com.block.common.service.ISourceDataCountInfoService;
import com.block.common.service.LogFactory;
import com.block.common.service.impl.ChannelCommonServcie;
import com.block.datapush.special.service.ISpecialCostomInfoService;
import com.block.db.entity.*;
import com.block.source.enums.ReceiveTypeEnum;
import com.block.source.factory.SourceApiFactory;
import com.block.source.model.dto.SourceApiParam;
import com.block.source.model.dto.SourceApiResult;
import com.block.source.service.*;
import com.block.test.reqbean.source.CheckUserInfo;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @Author: ld
 * @Date: 2024-08-26 16:30
 * @Description:
 * @Version: 1.0
 **/

@Service
@RequiredArgsConstructor
public class SourceHandleCheckUserV2ServiceImpl implements ISourceHandleCheckUserV2Service {

    private static Logger log = LogFactory.getSourceLog();

    private final ISourceBaseInfoService sourceBaseInfoService;
    private final IApplicationInfoService applicationInfoService;
    private final ChannelCommonServcie channelCommonServcie;
    private final ISpecialCostomInfoService specialCostomInfoService;
    private final ISourceCheckUserService sourceCheckUserService;
    private final NotifyExceptionService notifyExceptionService;
    private final ISourcePushResultInfoService sourcePushResultInfoService;
    private final ISourceRegisterUserService sourceRegisterUserService;
    private final ISourceDataCountInfoService sourceDataCountInfoService;

    @Override
    public JSONObject apiCheckUserV2(String channelCode, Map<String, String[]> parameterMap, String paramContent,
                                     String requestIp, String receiveType) {
        log.info("【线索api撞库】请求数据展示【channelCode】{}【parameterMap】{}【paramContent】{}", channelCode,
                JSON.toJSONString(parameterMap), paramContent);
        // 获取线索 对应的 处理类
        ISourceReceiveService sourceReceiveService = SourceApiFactory.getService(receiveType);
        if (sourceReceiveService == null) {
            return SourceApiFactory.getService(ReceiveTypeEnum.DEFAULT.getValue()).getError("渠道信息为空");
        }
        try {
            JSONObject jsonObjectParamContent = JSONObject.parseObject(paramContent);
            if (ObjectUtil.isEmpty(jsonObjectParamContent)){
                return sourceReceiveService.getError(null, "撞库传入的信息为空");
            }
            // 初始化返回值
            JSONObject resultObj = sourceReceiveService.resultInit(channelCode, jsonObjectParamContent.getString("requestId"), "fullAuthMatch");

            SourceBaseInfo sourceBaseInfo = sourceBaseInfoService.getSourceInfo(channelCode);
            if (ObjectUtil.isEmpty(sourceBaseInfo)){
                return sourceReceiveService.getError(resultObj, "渠道信息不可用");
            }
            if (!ObjectUtil.equals(sourceBaseInfo.getStatus(), Integer.valueOf(1))){
                return sourceReceiveService.getError(resultObj, "渠道信息不可用");
            }
            //渠道类型为双授权，类型才是正确的
            if (!ObjectUtil.equals(sourceBaseInfo.getType(), InfoTypeEnum.APIS.getValue())){
                return sourceReceiveService.getError(resultObj, "渠道类型错误，非双授权");
            }

            SourceCountDTO sourceCountDTO = new SourceCountDTO(sourceBaseInfo.getChannelCode(), sourceBaseInfo.getChannelName());
            sourceCountDTO.setCheckNumber(1);
            sourceDataCountInfoService.saveSourceCountInfo(sourceCountDTO);

            // 根据请求信息，构造需要的参数信息
            SourceApiResult sourceApiResult = sourceReceiveService.handleCheckUserData(sourceBaseInfo, parameterMap, paramContent);
            log.info("【线索api撞库】撞库数据转换完毕【channelCode】{}【sourceApiResult】{}", channelCode, JSON.toJSONString(sourceApiResult));
            if (!sourceApiResult.isSuccess()){
                return sourceReceiveService.getError(resultObj, sourceApiResult.getErrMsg());
            }
            // 执行撞库操作
            CheckUserInfo checkUserInfo = sourceApiResult.getCheckUserInfo();
            checkUserInfo.setUserIp(requestIp);

            // 撞库参数校验
            String respMsg = ISourceReceiveService.verifyCheckUserParam(checkUserInfo);
            // 返回信息不为空，则有异常，直接返回
            if (StrUtil.isNotEmpty(respMsg)) {
                log.info("【线索api撞库】撞库数据检验【channelCode】{}【verifyRes】{}", channelCode, respMsg);
                return sourceReceiveService.getError(resultObj, respMsg);
            }
            //
            ChannelInfo channelBaseInfo = channelCommonServcie.getChannelInfoCache(channelCode);
            ApplicationInfo applicationInfo = applicationInfoService.getAppInfoByType(channelBaseInfo.getAppType());

            ResultInfoVO resultInfoVO = sourceCheckUserService.sourceCheckUser1(sourceBaseInfo, checkUserInfo, channelBaseInfo, applicationInfo);
            log.info("【线索api撞库】数据撞库完成【channelCode】{}【resultInfoVO】{}", channelCode, JSON.toJSONString(resultInfoVO));
            if (!resultInfoVO.isSuccess()){
                return sourceReceiveService.getError(resultObj, resultInfoVO.getRespMsg());
            }

            // 根据返回结果，构造渠道方需要的数据
            JSONObject data = resultInfoVO.getData();
            String status = data.getString("status");
            if (!StrUtil.equals(status, "000")){
                return sourceReceiveService.getError(resultObj, "撞库失败");
            }

            String orderNo = data.getString("orderNo");
            SourcePushResultInfo sourcePushResultInfo = sourcePushResultInfoService.getById(orderNo);
            SpecialCostomInfo specialCostomInfo = specialCostomInfoService.getById(sourcePushResultInfo.getInfoId());

            MerchantThirdBaseInfo thirdBaseInfo = data.getObject("thirdBaseInfo", MerchantThirdBaseInfo.class);
            List<MerchantThirdProtocolInfo> thirdProtocolInfoList = data.getObject("thirdProtocolInfoList", List.class);

            SourceApiParam sourceApiParam = new SourceApiParam();
            sourceApiParam.setSourcePushResultInfo(sourcePushResultInfo);
            sourceApiParam.setSpecialCostomInfo(specialCostomInfo);
            sourceApiParam.setThirdBaseInfo(thirdBaseInfo);
            sourceApiParam.setThirdProtocolInfoList(thirdProtocolInfoList);
            sourceApiParam.setExtObject(sourceApiResult.getExtObject());

            // 根据请求信息，构造需要的参数信息
            SourceApiResult checkUserResult = sourceReceiveService.getCheckUserReturnData(sourceBaseInfo, resultInfoVO, sourceApiParam, checkUserInfo.getMobileMd5());

            // 返回数据
            log.info("【线索api撞库】请求完成，返回撞库数据【channelCode】{}【checkUserResult】{}", channelCode, JSON.toJSONString(checkUserResult));
            return sourceReceiveService.getSuccess(resultObj, checkUserResult.getReturnObject());
        }catch (Exception exception){
            // notifyExceptionService.notifyNoticeInfo("SOURCE_API_CHECK_EXEC", "线索api撞库异常", message, exception);
            log.error("线索api撞库异常", exception);
        }
        return sourceReceiveService.getError(null, "999999", "撞库异常");
    }

    @Override
    public JSONObject apiRegisterUserV2(String channelCode, Map<String, String[]> parameterMap, String paramContent, String requestIp, String receiveType){

        log.info("【线索api进件】请求数据展示【channelCode】{}【parameterMap】{}【paramContent】{}", channelCode, JSON.toJSONString(parameterMap), paramContent);
        // 获取线索 对应的 处理类
        ISourceReceiveService sourceReceiveService = SourceApiFactory.getService(receiveType);
        if (sourceReceiveService == null) {
            return SourceApiFactory.getService(ReceiveTypeEnum.DEFAULT.getValue()).getError("渠道信息为空");
        }
        try {
            JSONObject jsonObjectParamContent = JSONObject.parseObject(paramContent);
            if (ObjectUtil.isEmpty(jsonObjectParamContent)){
                return sourceReceiveService.getError(null, "进件传入的信息为空");
            }
            // 初始化返回值
            JSONObject resultObj = sourceReceiveService.resultInit(channelCode, jsonObjectParamContent.getString("requestId"), "apply");

            SourceBaseInfo sourceBaseInfo = sourceBaseInfoService.getSourceInfo(channelCode);
            if (ObjectUtil.isEmpty(sourceBaseInfo)){
                return sourceReceiveService.getError(resultObj,"渠道信息为空");
            }
            if (!ObjectUtil.equals(sourceBaseInfo.getStatus(), Integer.valueOf(1))){
                return sourceReceiveService.getError(resultObj,"渠道信息不可用");
            }
            if (!ObjectUtil.equals(sourceBaseInfo.getType(), InfoTypeEnum.APIS.getValue())){
                return sourceReceiveService.getError(resultObj,"渠道类型错误，非双授权");
            }

            SourceCountDTO sourceCountDTO = new SourceCountDTO(sourceBaseInfo.getChannelCode(), sourceBaseInfo.getChannelName());
            sourceCountDTO.setRegisterNumber(1);
            sourceDataCountInfoService.saveSourceCountInfo(sourceCountDTO);

            // 根据请求信息，构造需要的参数信息
            SourceApiResult sourceApiResult = sourceReceiveService.handleRegisterUserData(sourceBaseInfo, parameterMap, paramContent);
            log.info("【线索api进件】进件数据转换完毕【channelCode】{}【sourceApiResult】{}", sourceBaseInfo.getChannelCode(), JSON.toJSONString(sourceApiResult));
            if (!sourceApiResult.isSuccess()){
                return sourceReceiveService.getError(resultObj, sourceApiResult.getErrMsg());
            }
            CheckUserInfo userDataParam = sourceApiResult.getCheckUserInfo();
            userDataParam.setUserIp(requestIp);
            // 进行数据进件
            ResultInfoVO resultInfoVO = sourceRegisterUserService.sourceRegisterUser1(userDataParam.getOrderNo(), sourceBaseInfo, userDataParam);
            log.info("【线索api进件】数据进件完成【channelCode】{}【resultInfoVO】{}", channelCode, JSON.toJSONString(resultInfoVO));
            if (!resultInfoVO.isSuccess()){
                return sourceReceiveService.getError(resultObj, resultInfoVO.getRespMsg());
            }

            // 根据返回结果，构造渠道方需要的数据
            JSONObject data = resultInfoVO.getData();

            MerchantThirdBaseInfo thirdBaseInfo = data.getObject("thirdBaseInfo", MerchantThirdBaseInfo.class);
            List<MerchantThirdProtocolInfo> thirdProtocolInfoList = data.getObject("thirdProtocolInfoList", List.class);

            // 根据请求信息，构造需要的参数信息
            SourceApiParam sourceApiParam = new SourceApiParam();
            sourceApiParam.setExtObject(sourceApiResult.getExtObject());

            SourcePushResultInfo sourcePushResultInfo = sourcePushResultInfoService.getById(userDataParam.getOrderNo());

            SpecialCostomInfo specialCostomInfo = specialCostomInfoService.getById(sourcePushResultInfo.getInfoId());
            sourceApiParam.setSpecialCostomInfo(specialCostomInfo);
            sourceApiParam.setSourcePushResultInfo(sourcePushResultInfo);

            sourceApiParam.setThirdBaseInfo(thirdBaseInfo);
            sourceApiParam.setThirdProtocolInfoList(thirdProtocolInfoList);

            SourceApiResult checkUserResult = sourceReceiveService.getRegisterUserReturnData(sourceBaseInfo, resultInfoVO,sourceApiParam);
            // 返回数据
            log.info("【线索api进件】请求完成，返回进件数据【channelCode】{}【checkUserResult】{}", channelCode, JSON.toJSONString(checkUserResult));
            if (checkUserResult.isSuccess()) {

                sourceCountDTO.setRegisterPassNumber(1);
                sourceCountDTO.setRegisterNumber(null);
                sourceDataCountInfoService.saveSourceCountInfo(sourceCountDTO);

                return sourceReceiveService.getSuccess(resultObj, checkUserResult.getReturnObject());
            }
            return sourceReceiveService.getError(resultObj, "进件失败");
        }catch (Exception exception){
            log.error("进件异常", exception);
            // notifyExceptionService.notifyNoticeInfo("SOURCE_API_REGSTER_EXEC", "线索api进件异常", message, exception);
        }
        return sourceReceiveService.getError(null, "999999", "进件异常");
    }


}
